package io.gitee.zhangbinhub.acp.core.common.tools

import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormat

/**
 * @since JDK 17
 */
object Calculation {
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    const val DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"

    /**
     * yyyy-MM-dd
     */
    const val DATE_FORMAT = "yyyy-MM-dd"

    /**
     * 根据时间戳获取日期对象
     *
     * @param instant 时间戳
     * @return 日期对象
     */
    fun getCalendar(instant: Long): DateTime = DateTime(instant)

    /**
     * 获取日期对象
     *
     * @param dateTimeStr    日期字符串
     * @param dateTimeFormat 格式字符串
     * @return 日期对象
     */
    fun getCalendar(dateTimeStr: String, dateTimeFormat: String = DATE_FORMAT): DateTime =
        DateTimeFormat.forPattern(dateTimeFormat).parseDateTime(dateTimeStr)

    /**
     * 获取指定日期的后一天
     *
     * @param dateTime 日期对象
     * @return 日期对象
     */
    fun getNextDay(dateTime: DateTime): DateTime = dateTime.plusDays(1)

    /**
     * 获取指定日期前一天
     *
     * @param dateTime 日期对象
     * @return 日期对象
     */
    fun getPrevDay(dateTime: DateTime): DateTime = dateTime.minusDays(1)

    /**
     * 获取指定日期是一周中第几天
     *
     * @param dateTime 日期对象
     * @return 结果（1-7）,其中sunday是7
     */
    fun getWeekNo(dateTime: DateTime): Int = dateTime.dayOfWeek

    /**
     * 获取指定日期日号
     *
     * @param dateTime 日期对象
     * @return 日号（1-31）
     */
    fun getDayNo(dateTime: DateTime): Int = dateTime.dayOfMonth

    /**
     * 获取指定月号
     *
     * @param dateTime 日期对象
     * @return 月号（1-12）
     */
    fun getMonthNo(dateTime: DateTime): Int = dateTime.monthOfYear

    /**
     * 获取指定月所在季度内的月号
     *
     * @param dateTime 日期对象
     * @return 季度内的月号（1, 2, 3）
     */
    fun getMonthNoInQuarter(dateTime: DateTime): Int {
        val month = getMonthNo(dateTime)
        return if (month in 1..12) {
            (month % 3).let {
                if (it == 0) {
                    3
                } else {
                    it
                }
            }
        } else {
            -1
        }
    }

    /**
     * 获取指定月最后一天日号
     *
     * @param dateTime 日期对象
     * @return 日号
     */
    fun getLastDayInMonthNo(dateTime: DateTime): Int = dateTime.dayOfMonth().withMaximumValue().dayOfMonth

    /**
     * 判断当前时间是否是工作日
     *
     * @param dateTime 日期对象
     * @return 是否是工作日
     */
    fun isWeekDay(dateTime: DateTime): Boolean = getWeekNo(dateTime) < 6

    /**
     * 判断当前时间是否是周末
     *
     * @param dateTime 日期对象
     * @return 是否是周末
     */
    fun isWeekend(dateTime: DateTime): Boolean = getWeekNo(dateTime) > 5

    /**
     * 获取指定时间的当月第一天0点0分0秒
     *
     * @param dateTime 指定日期时间
     * @return 指定日期的0点0分0秒
     */
    fun currMonthFirstDay(dateTime: DateTime): DateTime =
        dateZero(dateTime.withDayOfMonth(1))

    /**
     * 获取指定时间的次月第一天0点0分0秒
     *
     * @param dateTime 指定日期时间
     * @return 指定日期的0点0分0秒
     */
    fun nextMonthFirstDay(dateTime: DateTime): DateTime =
        dateZero(currMonthFirstDay(dateTime.plusMonths(1)))

    /**
     * 获取指定时间的0点0分0秒
     *
     * @param dateTime 指定日期时间
     * @return 指定日期的0点0分0秒
     */
    fun dateZero(dateTime: DateTime): DateTime =
        dateTime.withHourOfDay(0)
            .withMinuteOfHour(0)
            .withSecondOfMinute(0)
            .withMillisOfSecond(0)

    /**
     * local时间转换成UTC时间
     */
    fun localToUtc(localDateTime: DateTime): DateTime =
        localDateTime.toDateTime(DateTimeZone.UTC)

    /**
     * utc时间转成local时间
     */
    fun utcToLocal(utcDateTime: DateTime): DateTime =
        utcDateTime.toDateTime(DateTimeZone.getDefault())
}